<template>
	<div>
		<el-input placeholder="输入关键字进行过滤" v-model="filterText" clearable></el-input>

		<el-collapse-transition>
			<div v-if="power">
				<el-divider content-position="left">操作</el-divider>
				<el-button style="text-align: left;" @click.stop="appendRootPath()">
					<i class="el-icon-circle-plus-outline"></i>
					<span>新增根目录</span>
				</el-button>
				<el-tooltip class="item" effect="dark" content="右击节点操作" placement="top-start">
					<el-divider content-position="left">节点</el-divider>
				</el-tooltip>
			</div>
		</el-collapse-transition>

		<el-tree class="filter-tree" :data="Nav.source.data" :props="{children: 'children',label: 'label'}"
			default-expand-all :filter-node-method="filterNode" :draggable="power" node-key="id" ref="tree"
			highlight-current :allow-drop="allowDrop" @node-contextmenu="rightClick" @node-click="nodeClick">
			<span class="custom-tree-node" slot-scope="{ node, data }">
				<span :class="{'path': data.type==='path'}">{{ node.label }}</span>
			</span>
		</el-tree>

		<div v-show="menuVisible" ref="menu" class="menu">
			<div v-if="selectNode.Node && selectNode.Node.data.type=='path'">
				<div class="contextmenu__item" @click.stop="reName(selectNode.Node)">重命名</div>
				<div class="contextmenu__item" @click.stop="appendPath(selectNode.Node)">添加目录</div>
				<div class="contextmenu__item" @click.stop="appendApi(selectNode.Node)">添加接口</div>
				<div class="contextmenu__item" @click.stop="remove(selectNode.Node,selectNode.data)">删除</div>
			</div>
			<div v-if="selectNode.Node && selectNode.Node.data.type=='file'">
				<div class="contextmenu__item" @click.stop="reName(selectNode.Node)">重命名</div>
				<div class="contextmenu__item" @click.stop="copyNode(selectNode.Node,selectNode.data)">复制</div>
				<div class="contextmenu__item" @click.stop="remove(selectNode.Node,selectNode.data)">删除</div>
			</div>
		</div>
	</div>
</template>

<script>
	export default {
		name: 'Nav',
		props: {
			power: {
				type: Boolean,
			},
			Nav: {
				type: Object,
			}
		},
		model: ['Nav'],
		data() {
			return {
				menuVisible: false,
				selectNode: { // 右击选中的节点信息
					Node: null,
					data: null
				},
				filterText: '',
			}
		},
		methods: {
			filterNode(value, data) {
				// 筛选节点
				if (!value) return true
				return data.label.indexOf(value) !== -1
			},
			Trim(str) {
				return str.replace(/(^\s*)|(\s*$)/g, "");
			},
			appendRootPath() {
				// 新增根目录
				this.$prompt('新根目录', '添加', {
					confirmButtonText: '确定',
					cancelButtonText: '取消',
					inputValue: ''
				}).then((el) => {
					let val = this.Trim(el.value)
					if (val == '') {
						this.$message.error('空参数!')
						this.menuVisible = false
						return
					}
					for (let item of this.Nav.source.data) {
						if (item.type === 'path' && item.label === val) {
							this.$message.error('同级别下存在相同目录');
							return
						}
					}
					this.Nav.source.data.push({
						id: ++this.Nav.source.dataId,
						label: val,
						type: 'path',
						children: []
					})
				}).catch(() => {})
			},
			appendPath(Node) {
				// 添加目录
				if (Node.level > 10) {
					this.$message.error('迭代层数过多！')
					return
				}
				this.$prompt('新目录', '添加', {
					confirmButtonText: '确定',
					cancelButtonText: '取消',
					inputValue: ''
				}).then((el) => {
					let val = this.Trim(el.value)
					if (val == '') {
						this.$message.error('空参数!')
						this.menuVisible = false
						return
					}
					for (let item of Node.childNodes) {
						if (item.data.type === 'path' && item.data.label === val) {
							this.$message.error('同级别下存在相同目录');
							return
						}
					}
					this.Nav.tree.append({
						id: ++this.Nav.source.dataId,
						label: val,
						type: 'path',
						children: []
					}, Node)
					this.menuVisible = false
				}).catch(() => {})
			},


			appendApi(Node) {
				// 添加接口
				if (Node.level > 10) {
					this.$message.error('迭代层数过多！')
					return
				}
				this.$prompt('新接口', '添加', {
					confirmButtonText: '确定',
					cancelButtonText: '取消',
					inputValue: '',
				}).then((el) => {
					let val = this.Trim(el.value)
					if (val == '') {
						this.$message.error('空参数!')
						this.menuVisible = false
						return
					}
					for (let item of Node.childNodes) {
						if (item.data.type === 'file' && item.data.label === val) {
							this.$message.error('同级别下存在相同接口!');
							return
						}
					}
					this.Nav.tree.append({
						id: ++this.Nav.source.dataId,
						label: val,
						type: 'file'
					}, Node)
					this.Nav.source.source[this.Nav.source.dataId] = this.$config.default_json
					this.menuVisible = false
				}).catch(() => {})
			},
			remove(node, data) {
				// 删除节点
				this.$confirm(`确认删除 ${data.label}?`, '删除', {
					confirmButtonText: '确定',
					cancelButtonText: '取消',
					type: 'warning'
				}).then(() => {
					let parent = node.parent;
					let children = parent.data.children || parent.data;
					let index = children.findIndex(d => d.id === data.id);
					this.$delete(this.Nav.source.source, data.id)
					children.splice(index, 1);
					this.menuVisible = false
				}).catch(() => {})
			},
			allowDrop(moveNode, inNode, Type) {
				// 移动节点后
				if (inNode.data.type == "file" && Type == "inner")
					return false
				return true
			},


			reName(Node) {
				// 重命名节点
				this.$prompt('重命名节点', '重命名', {
					confirmButtonText: '确定',
					cancelButtonText: '取消',
					inputValue: Node.data.label
				}).then((el) => {
					let val = this.Trim(el.value)
					if (val == '') {
						this.$message.error('空参数!')
						this.menuVisible = false
						return
					}
					for (let item of Node.parent.childNodes) {
						if (item.data.type === Node.data.type && item.data.label === val) {
							this.$message.error('同名冲突');
							return
						}
					}
					Node.data.label = val
					this.menuVisible = false
				}).catch(() => {})
			},


			copyNode(Node, data) {
				// 复制节点
				this.$prompt('新接口', '复制', {
					confirmButtonText: '确定',
					cancelButtonText: '取消',
					inputValue: data.label + ' copy'
				}).then((el) => {
					let val = this.Trim(el.value)
					if (val == '') {
						this.$message.error('空参数!')
						this.menuVisible = false
						return
					}
					for (let item of Node.parent.childNodes) {
						if (item.data.type === Node.data.type && item.data.label === val) {
							this.$message.error('同名冲突');
							return
						}
					}
					this.Nav.tree.append({
						id: ++this.Nav.source.dataId,
						label: val,
						type: 'file'
					}, Node.parent)
					let i = JSON.parse(JSON.stringify(this.Nav.source.source[data.id]))
					this.Nav.source.source[this.Nav.source.dataId] = i
					this.menuVisible = false
				}).catch(() => {})
			},
			nodeClick(row, column) {
				// 点击节点
				this.Nav.Node = column
			},
			rightClick(row, column, Node) {
				// 右击节点 
				if (!this.power) return
				this.selectNode = {
					Node: Node,
					data: column
				}

				this.menuVisible = false // 先把模态框关死，目的是 第二次或者第n次右键鼠标的时候 它默认的是true
				this.menuVisible = true // 显示模态窗口，跳出自定义菜单栏

				var menu = this.$refs.menu //document.querySelector('.menu')	
				this.styleMenu(menu)
			},
			foo() {
				// 取消鼠标监听事件 菜单栏
				this.menuVisible = false
				document.removeEventListener('click', this.foo) // 关掉监听，
			},
			styleMenu(menu) {
				if (event.clientX > 1800) {
					menu.style.left = event.clientX - 100 + 'px'
				} else {
					menu.style.left = event.clientX + 1 + 'px'
				}
				document.addEventListener('click', this.foo) // 给整个document新增监听鼠标事件，点击任何位置执行foo方法
				if (event.clientY > 700) {
					menu.style.top = event.clientY - 30 + 'px'
				} else {
					menu.style.top = event.clientY - 10 + 'px'
				}
			},
		},
		watch: {
			filterText(val) {
				this.$refs.tree.filter(val);
			},
		},
		created() {
			setTimeout(() => {
				this.Nav.tree = this.$refs.tree
				this.Nav.Node = this.Nav.tree.root
				//console.log(this.Nav.tree.root)
				//this.Nav.Node = this.Nav.tree.root.childNodes[0].childNodes[0]
			}, 10)
		}
	}
</script>

<style scoped>
	.custom-tree-node {
		flex: 1;
		display: flex;
		align-items: center;
		justify-content: space-between;
		font-size: 14px;
		padding-right: 8px;
	}

	.btn {
		margin-top: 10px;
	}

	.path {
		font-size: 16px;
		font-weight: 800;
	}

	.help {
		font-size: 14px;
	}

	.active {
		border: 1px solid #66B1FF;
		border-radius: 8px;
	}


	.menu {
		position: absolute;
		background-color: #fff;
		width: 100px;
		/*height: 106px;*/
		font-size: 12px;
		color: #444040;
		border-radius: 4px;
		-webkit-box-sizing: border-box;
		box-sizing: border-box;
		border-radius: 3px;
		border: 1px solid rgba(0, 0, 0, 0.15);
		box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
		white-space: nowrap;
		z-index: 1000;

		transition: all .3s ease-in-out;
	}

	.contextmenu__item {
		display: block;
		line-height: 34px;
		text-align: center;
		transition: all .2s;
	}

	.contextmenu__item:not(:last-child) {
		border-bottom: 1px solid rgba(0, 0, 0, 0.1);
	}

	.contextmenu__item:hover {
		cursor: pointer;
		background: #66b1ff;
		border-color: #66b1ff;
		color: #fff;
		transition: all .2s;
	}
</style>
